home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Your Choice 1
/
your choice.zip
/
your choice
/
PRGMMING
/
VISIONIX
/
VSTATEU.PAS
< prev
next >
Wrap
Pascal/Delphi Source File
|
1993-12-30
|
9KB
|
344 lines
{
════════════════════════════════════════════════════════════════════════════
Visionix Finite State Machine (VStateu) Unit
Version 0.7
Copyright 1991,92,93 Visionix
ALL RIGHTS RESERVED
────────────────────────────────────────────────────────────────────────────
Revision history in reverse chronological order:
Initials Date Comment
──────── ──────── ───────────────────────────────────────────────────────
jrt 11/02/93 First logged revision.
════════════════════════════════════════════════════════════════════════════
}
(*-
[TEXT]
<Overview>
This unit includes functions to assist in the creation and usage
of finate state machine based programs. It includes functions to
create state machines, add states to machines, track states, remove
states, and execute state machines.
<Interface>
-*)
Unit VStateu;
Interface
Uses
VTypesu;
Const
{------------------------------------------}
{ constant returned by a state to tell the }
{ state machine to stop }
{------------------------------------------}
cstateMachineStop = -1;
{-----------------------}
{ VStateMachineDo flags }
{-----------------------}
cSmStopOnEveryState = $0001; { explicit stop after EVERY state }
{---------------------------------------}
{ debug messages for the debug function }
{---------------------------------------}
csmdStateMachineStarted = $0001;
csmdStatePre = $0002;
csmdStatePost = $0003;
csmdStateMachineStopped = $0004;
Type
{---------------------}
{ state function type }
{---------------------}
TStateFunc = FUNCTION ( StateID : INTEGER;
nexus : POINTER ) : INTEGER;
{----------------------------}
{ per-state info record type }
{----------------------------}
TStateName = STRING[40];
TState = RECORD
StateID : INTEGER;
StateName : TStateName;
StateFunc : TStateFunc;
END;
PState = ^TState;
{-----------------------------------}
{ state machine debug function type }
{-----------------------------------}
TStateDebugFunc = FUNCTION ( Msg : LONGINT;
StateID : INTEGER;
StateName : TStateName;
nexus : POINTER ) : INTEGER;
{------------------------}
{ The state machine type }
{------------------------}
TStateMachine = RECORD
NumStatesAlloc : INTEGER;
CurNumStates : INTEGER;
DebugFunc : TStateDebugFunc;
State : Array[1..1] of TState;
END;
PStateMachine = ^TStateMachine;
{────────────────────────────────────────────────────────────────────────────}
Function VStateMachineNew( Flags : WORD;
NumStates : INTEGER ) : PStateMachine;
Procedure VStateMachineDispose( SM : PStateMachine );
Procedure VStateMachineDebug( SM : PStateMachine;
DebugFunc : TStateDebugFunc );
Procedure VStateMachineAdd( SM : PStateMachine;
StateID : INTEGER;
StateName : TStateName;
StateFunc : TStateFunc );
Function VStateMachineStart( SM : PStateMachine;
Flags : WORD;
StartStateID : INTEGER;
Nexus : POINTER ) : INTEGER;
{────────────────────────────────────────────────────────────────────────────}
Implementation
Function VStateMachineNew( Flags : WORD;
NumStates : INTEGER ) : PStateMachine;
Var
NSM : PStateMachine;
BEGIN
GetMem( NSM, SizeOf( TStateMachine ) +
( SizeOf(TState) * (NumStates-1) ) );
NSM^.NumStatesAlloc := NumStates;
NSM^.CurNumStates := 0;
@NSM^.DebugFunc := NIL; { !! version 6.0 bug }
VStateMachineNew := NSM;
END;
{────────────────────────────────────────────────────────────────────────────}
Procedure VStateMachineDispose( SM : PStateMachine );
BEGIN
FreeMem( SM, SizeOf( TStateMachine ) +
( SizeOf(TState) * (SM^.NumStatesAlloc-1) ) );
END;
{────────────────────────────────────────────────────────────────────────────}
Procedure VStateMachineDebug( SM : PStateMachine;
DebugFunc : TStateDebugFunc );
BEGIN
SM^.DebugFunc := DebugFunc;
END;
{────────────────────────────────────────────────────────────────────────────}
Procedure VStateMachineAdd( SM : PStateMachine;
StateID : INTEGER;
StateName : TStateName;
StateFunc : TStateFunc );
Var
Z : INTEGER;
BEGIN
If SM^.CurNumStates<SM^.NumStatesAlloc Then
BEGIN
Inc( SM^.CurNumStates );
Z := SM^.CurNumStates;
SM^.State[Z].StateID := StateId;
SM^.State[Z].StateName := StateName;
SM^.State[Z].StateFunc := StateFunc;
END;
END;
{────────────────────────────────────────────────────────────────────────────}
Function VStateMachineStart( SM : PStateMachine;
Flags : WORD;
StartStateID : INTEGER;
Nexus : POINTER ) : INTEGER;
Var
CurStateID : INTEGER;
NextStateID : INTEGER;
Z : INTEGER;
BEGIN
{----------------------------------------------}
{ start off looking for the specified state ID }
{----------------------------------------------}
NextStateId := StartStateID;
{---------------------------------------------}
{ if a debug proc has been specified, tell it }
{ that we are starting the state machine }
{---------------------------------------------}
If @SM^.DebugFunc<>NIL Then
SM^.DebugFunc( csmdStateMachineStarted,
NextStateId,
'',
Nexus );
{-----------------------------------------}
{ do the state machine until it says STOP }
{ or stop because the cSMStopOnEveryState }
{ flag is set. }
{-----------------------------------------}
Repeat
{--------------------------}
{ look for the nextStateID }
{ until we find it or we }
{ checked all the states }
{--------------------------}
Z := 1;
While (SM^.State[Z].StateID<>NextStateID) and
(Z<=SM^.CurNumStates ) Do
Inc( Z );
{------------------------------}
{ Did we find the nextstateID? }
{------------------------------}
If SM^.State[Z].StateID=NextStateID Then
BEGIN
{----------------------}
{ yep, go do the state }
{----------------------}
CurStateID := NextStateID;
{----------------------------------------------}
{ if a debug proc has been set, tell it we are }
{ before the state }
{----------------------------------------------}
If @SM^.DebugFunc<>NIL Then
SM^.DebugFunc( csmdStatePre,
CurStateId,
SM^.State[Z].Statename,
Nexus );
NextStateID := SM^.State[Z].StateFunc( CurStateID, Nexus );
{----------------------------------------------}
{ if a debug proc has been set, tell it we are }
{ after the state }
{----------------------------------------------}
If @SM^.DebugFunc<>NIL Then
SM^.DebugFunc( csmdStatePost,
CurStateId,
SM^.State[Z].Statename,
Nexus );
END
ELSE
NextStateID := cStateMachineStop;
Until (NextStateID=cStateMachineStop ) or
(Flags and cSMStopOnEveryState>0);
{----------------------------------------------}
{ if a debug proc has been set, tell it we are }
{ stopping the state machine }
{----------------------------------------------}
If @SM^.DebugFunc<>NIL Then
SM^.DebugFunc( csmdStateMachineStopped,
CurStateId,
'',
Nexus );
VStateMachineStart := CurStateId;
END;
{────────────────────────────────────────────────────────────────────────────}
{────────────────────────────────────────────────────────────────────────────}
{────────────────────────────────────────────────────────────────────────────}
BEGIN
END.